package vmi.surgis;

import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

public class MapView {
	PointF selectedPos;
	
	ImageView map;
	ImageView pointer;
	TextView label;
	
	PointF pointerPos = new PointF(0,0);
	PointF mapPos = new PointF(0,0);
	float mapScale = 1.0f;
	
	final int screenW;
	final int screenH;
	
	final int mapW;
	final int mapH;
	
	private float mapScaledW()
	{
		return mapW*mapScale;
	}
	private float mapScaledH()
	{
		return mapH*mapScale;
	}
	
	final float POINTER_HALF_WIDTH = 21;
	final float MIN_SCALE;
	final float MAX_SCALE;
	
	public PointF getCenter()
	{
		return new PointF((-mapPos.x + screenW/2)/mapScale, (-mapPos.y + screenH/2)/mapScale);
	}
	
	public MapView(ImageView m, ImageView p, TextView l, int screenWidth, int screenHeight)
	{
		map = m;
		pointer = p;
		label = l;
		pointer.setVisibility(View.INVISIBLE);
		label.setVisibility(View.INVISIBLE);
		
		screenW = screenWidth;
		screenH = screenHeight;
		
		mapW = 1800;
		mapH = 1000;
		
		MIN_SCALE = Math.max(Math.max((float)screenW/mapW, (float)screenH/mapH), Math.max((float)screenW/mapH, (float)screenH/mapW));
		MAX_SCALE = 2f;
	}
	
	final private Matrix pointerMatrix  = new Matrix(); 
	final private Matrix mapMatrix 	    = new Matrix();
	
	public PointF getTransformedPoint(PointF pos)
	{
		return new PointF((-mapPos.x + pos.x)/mapScale, (-mapPos.y + pos.y)/mapScale);
	}
	
	public void centerMap(PointF center)
	{
		this.Scroll((center.x*mapScale+mapPos.x-screenW/2), (center.y*mapScale+mapPos.y-screenH/2));
	}
	public void placePointer(Place p)
	{
		pointerPos = p.position;
		pointer.setVisibility(View.VISIBLE);
		label.setVisibility(View.VISIBLE);
		label.setText(p.name + "\n" + p.getTimeString());
		label.setShadowLayer(2f, 0f, 0f, Color.BLACK);
		centerMap(pointerPos);
	}
	
	public void updateMap()
	{
		mapMatrix.reset();

		if (mapScale < MIN_SCALE)
		{
			mapScale = MIN_SCALE;
		}
		if (mapScale > MAX_SCALE)
		{
			mapScale = MAX_SCALE;
		}
		mapMatrix.postScale(mapScale, mapScale);
		mapMatrix.postTranslate(mapPos.x, mapPos.y);
		map.setImageMatrix(mapMatrix);
		ScrollRestriction();
		updatePointerPosition();
	}
	public void updatePointerPosition()
	{
		if (pointer.getVisibility() == View.VISIBLE)
		{
			pointerMatrix.reset();
			pointerMatrix.postTranslate(pointerPos.x*mapScale + mapPos.x - POINTER_HALF_WIDTH, pointerPos.y*mapScale + mapPos.y - POINTER_HALF_WIDTH*2);
			pointer.setImageMatrix(pointerMatrix);
			label.setPadding((int)(pointerPos.x*mapScale + mapPos.x), (int)(pointerPos.y*mapScale + mapPos.y), 0, 0);
		}
	}
	
	private void ScrollRestriction()
	{
		float minX = -mapScaledW() + screenW;
		float minY = -mapScaledH() + screenH;
		float distanceX = 0f;
		float distanceY = 0f;
		
		if (mapPos.x > 0 || mapScaledW() < screenW)
		{
			distanceX += mapPos.x;
			mapPos.x = 0;
		}
		if (mapPos.x < minX)
		{
			distanceX += mapPos.x - minX;
			mapPos.x = minX;
		}
	
		if (mapPos.y > 0 || mapScaledH() < screenH)
		{
			distanceY += mapPos.y;
			mapPos.y = 0;
		}
		if (mapPos.y < minY)
		{
			distanceY += mapPos.y - minY;
			mapPos.y = minY;
		}
		
		mapMatrix.postTranslate(-distanceX, -distanceY);
		map.setImageMatrix(mapMatrix);		
		updatePointerPosition();
	}
	public void Scroll(Float distanceX, Float distanceY)
	{
		mapPos.x -= distanceX;
		mapPos.y -= distanceY;
		
		mapMatrix.postTranslate(-distanceX, -distanceY);
		map.setImageMatrix(mapMatrix);

		ScrollRestriction();
	}
	
	public void Zoom(float scale)
	{
		float X = screenW/2;
		float Y = screenH/2;
		Zoom(scale, new PointF(X, Y));
	}
	public void Zoom(float scale, PointF mid)
	{
		Log.w(null, " " + MIN_SCALE + " " + scale);
		if ((mapScale < MIN_SCALE && scale < 1f) || (mapScale > MAX_SCALE && scale > 1f))
		{
			scale = 1f;
		}
		
		mapScale *= scale;
		
		if (mapScale < MIN_SCALE)
		{
			scale = MIN_SCALE / mapScale * scale;
			mapScale = MIN_SCALE;
		}
		
		if (mapScale > MAX_SCALE)
		{
			scale = MAX_SCALE / mapScale * scale;
			mapScale = MAX_SCALE;
		}
		
		mapPos.x = mid.x - (mid.x - mapPos.x) * scale;
		mapPos.y = mid.y - (mid.y - mapPos.y) * scale;
		
		mapMatrix.postScale(scale, scale, mid.x, mid.y);
		map.setImageMatrix(mapMatrix);
		
		ScrollRestriction();
	}
}
